package com.yjq.blog.article.utils;

import com.alibaba.fastjson.JSON;
import com.yjq.blog.vo.Response;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CometPullTask implements Runnable {

    Map<String, CometPullTask> cometTasks;
    ScheduledExecutorService scheduler;
    AsyncContext asyncContext;
    String sessionId;
    HttpServletRequest req;
    HttpServletResponse resp;

    Future<?> asyncTimeoutFuture;

    public CometPullTask(Map<String, CometPullTask> cometTasks, ScheduledExecutorService scheduler,
                         AsyncContext asyncContext, String sessionId, HttpServletRequest req, HttpServletResponse resp) {
        this.cometTasks = cometTasks;
        this.scheduler = scheduler;
        this.asyncContext = asyncContext;
        this.sessionId = sessionId;
        this.req = req;
        this.resp = resp;
    }

    @Override
    public void run() {
        asyncTimeoutFuture = scheduler.schedule(() -> {
            sendResponse(null);
            cometTasks.remove(sessionId);
        }, 10, TimeUnit.SECONDS);
        cometTasks.put(sessionId, this);
    }

    /**
     * 发送响应
     */
    public void sendResponse(String result) {
        // 取消等待执行的任务,避免已经响完了,还有资源被占用
        if (asyncTimeoutFuture != null) {
            // 设置为true会立即中断执行中的任务,false对执行中的任务无影响,但会取消等待执行的任务
            asyncTimeoutFuture.cancel(false);
        }

        resp.setContentType("application/json; charset=utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("Pragma", "no-cache");
        resp.setHeader("Cache-Control", "no-cache,no-store");
        resp.setDateHeader("Expires", 0);
        resp.setStatus(HttpServletResponse.SC_OK);

        sendJsonResult(result);
    }

    /**
     * 发送响应流
     */
    private void sendJsonResult(String result) {
        Response<String> resultResponse = Response.success(result);
        try (PrintWriter writer = asyncContext.getResponse().getWriter()) {
            writer.write(JSON.toJSONString(resultResponse));
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            asyncContext.complete();
        }
    }
}